﻿using Se.Data;
using Se.Data.Sql;
using Se.Log;
using Se.Model.GameModel;
using Se.Reflection;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace Se.Model.Data
{
    /// <summary>
    /// 数据工厂
    /// </summary>
    public static class DataEntityFactory
    {
        static DataEntityFactory()
        {
            m_EntitySet = new Dictionary<string, DataEntityCollection>();
            m_EntityLoadType = new Dictionary<Type, DBLoadType>();
        }

        /// <summary>
        /// 保存整个Factory到数据库，参数state暂时不用
        /// </summary>
        /// <param name="state"></param>
        public static void SaveFactoryToDB(object state)
        {
            //每一个表一个线程
            foreach (var collectionItem in m_EntitySet)
            {
                //ThreadPool.QueueUserWorkItem(obj =>
                //{
                    var collection = collectionItem.Value;
                    List<long> deletedIDs;
                    SaveEntityToDB(collection, out deletedIDs);

                    //删除Delete标记的entity
                    deletedIDs.ForEach(id =>
                    {
                        collection.EntitySet.Remove(id);
                    });
                //});
            }
        }

        /// <summary>
        /// 保存到数据库
        /// </summary>
        /// <param name="collection"></param>
        /// <param name="deletedIDs">被标记为删除的ID</param>
        /// <returns></returns>
        private static void SaveEntityToDB(DataEntityCollection collection, out List<long> deletedIDs)
        {
            System.Diagnostics.Stopwatch watch = new System.Diagnostics.Stopwatch();
            watch.Start();
            Type t = Type.GetType(collection.EntityFullName);
            _dbManager.SaveEntityCollection(t, out deletedIDs, collection.EntitySet.Values.ToArray());
            watch.Stop();
            SeLog.Info("DataEntityFactory->SaveFactoryToDB:保存{0}消耗了时间：{1}毫秒", collection.EntityFullName, watch.ElapsedMilliseconds);
        }

        /// <summary>
        /// 数据集合
        /// </summary>
        private static Dictionary<string, DataEntityCollection> m_EntitySet;
        /// <summary>
        /// 数据加载类型
        /// </summary>
        private static Dictionary<Type, DBLoadType> m_EntityLoadType;

        /// <summary>
        /// 数据库提供者
        /// </summary>
        private static DBManager _dbManager;

        /// <summary>
        /// 定时存储器
        /// </summary>
        private static Timer _saveTimer;

        /// <summary>
        /// 开始，interval表示定时存储的定长（毫秒）
        /// </summary>
        /// <param name="interval">毫秒</param>
        public static void StartTimer(long interval)
        {
            _saveTimer = new Timer(SaveFactoryToDB, null, 0, interval);
        }

        /// <summary>
        /// 初始化
        /// </summary>
        /// <param name="sqlType"></param>
        /// <param name="connectionString"></param>
        public static void Initilize(SqlType sqlType, string connectionString)
        {
            switch (sqlType)
            {
                case SqlType.SQLServer:
                    _dbManager = new DBManager(new SqlDataProvider(connectionString));
                    break;
                default:
                    throw new ArgumentException("SqlType not exist");
            }
        }

        /// <summary>
        /// 注册模型集合
        /// </summary>
        /// <param name="name"></param>
        /// <param name="loadType"></param>
        public static bool TryRegisterEntityCollection(Type type, DBLoadType loadType)
        {
            if (!m_EntitySet.ContainsKey(type.Name))
            {
                m_EntitySet[type.Name] = new DataEntityCollection(loadType, type.FullName);
                m_EntityLoadType[type] = loadType;
                _dbManager.TryAddTable(type);
                // 初始化IdGenerator
                long minSerialID = 1;
                try
                {
                    string sql = "SELECT MAX(ID) FROM dbo." + type.Name + ";";
                    minSerialID = (long)_dbManager.GetDBScalar(sql) + 1;
                }
                catch { }
                finally
                {
                    DataEntityIDGenerator.AddIdGenerator(type.Name, minSerialID);
                }

                return true;
            }
            return false;
        }

        /// <summary>
        /// 获取Entity
        /// </summary>
        /// <param name="name"></param>
        /// <param name="id"></param>
        /// <returns></returns>
        public static T GetEntity<T>(long id) where T : DataEntityBase
        {
            var name = typeof(T).Name;
            if (m_EntitySet.ContainsKey(name))
            {
                var entities = m_EntitySet[name];
                DataEntityBase entity;
                if (entities.EntitySet.TryGetValue(id, out entity))
                {
                    return (T)entity;
                }
            }
            var dataEntity = GetDBEntity<T>(id);
            return dataEntity;
        }

        /// <summary>
        /// 从DB中获取Entity
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="id"></param>
        /// <returns></returns>
        private static T GetDBEntity<T>(long id) where T : DataEntityBase
        {
            var dataEntity = (T)_dbManager.GetEntity<T>(id);
            if (dataEntity == null) return null;

            var name = typeof(T).Name;
            m_EntitySet[name].AddEntity(dataEntity);
            dataEntity.IsInFactory = true;
            return dataEntity;
        }

        /// <summary>
        /// 获取Entity集合
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public static T[] GetEntity<T>() where T : DataEntityBase
        {
            var name = typeof(T).Name;
            var entitySet = m_EntitySet[name];
            if (entitySet.EntitySet.Count > 0)
            {
                return DBEntityCommon.ConvertEntityArray<T>(entitySet.EntitySet.Values.ToArray());
            }
            //从DB从取数据
            var entities = _dbManager.GetEntity<T>();
            foreach (var entity in entities)
            {
                entity.IsInFactory = true;
                entitySet.AddEntity(entity);
            }
            return entities;
        }

        /// <summary>
        /// 保存单个对象(标记为保存)
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="entity"></param>
        public static void SaveEntity(DataEntityBase entity)
        {
            if (!entity.IsInFactory)
            {
                var entityCollection = m_EntitySet[entity.GetType().Name];
                entityCollection.AddEntity(entity);
                entity.IsInFactory = true;
            }
            entity.IsDirty = true;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="fileName"></param>
        public static void ReadFile<T>(string fileName) where T : DataEntityBase
        {
            List<T> entities = new List<T>();
            //TODO
        }
    }
}
